package se.sics.tac.aw; 

import java.awt.Toolkit;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Logger;

public class HotelBidding {


	/**
	 * @param args
	 */

	//NOTE: FOR TESTING ONLY: NEEDS TO BE CHANGED LATER ON
	//	 private final String fileName="C:\\Users\\Alam\\workspace\\tacagent\\src\\se\\sics\\tac\\aw\\LastTenGames.ser";
	private final String fileName="LastTenGames.ser";
	private Vector<Vector> collection;
	private float avgValues[]=new float[8];



	private static final java.util.logging.Logger log =
		Logger.getLogger(AgentSnorky.class.getName());

	HotelBidding()
	{

		collection=readAvgFile();
		refreshAvgValues();

	}

	private void refreshAvgValues() {
		if (collection == null)
			return;
		int index=0;

		for (Object object : collection) {
			System.out.println(object);
			avgValues[index]= getAvg((Vector)(object));
			log.fine(""+avgValues[index]);
			index++;
		}
	}

	public float getAvgValueOfHotel(int hotel)
	{
		return avgValues[hotel];
	}

	private float getAvg(Vector v)
	{
		float avg=0;
		for (Object obj1 : v) {
			float value = 0f;
			if (obj1.getClass() == Float.class)
				value = ((Float) obj1).floatValue();
			else if (obj1.getClass() == Double.class)
				value = ((Double) obj1).floatValue();
			else if (obj1.getClass() == Integer.class)
				value = ((Integer) obj1).floatValue();
			avg+=value;
		}
		//Send a little higher than the average
		if (v.size()>0)
			return (float)((avg/=v.size())*1.25);
		else
			return 0f;

	}




	private Vector<Vector> readAvgFile()
	{
		Vector<Vector> avg=null;

		try {
			InputStream file=new FileInputStream(fileName);
			InputStream buffer=new BufferedInputStream(file);
			ObjectInput input=new ObjectInputStream(buffer);

			try
			{
				avg=(Vector<Vector>)input.readObject();

			}

			finally
			{
				input.close();
			}
		} 

		catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		return avg;


	}

	public  void insertNewAvg(float arr[])
	{
		Vector<Float> newVal=new Vector<Float>();

		for (int i = 0; i < arr.length; i++) {
			newVal.add(new Float(arr[i]));
		}

		int index=0;
		for(int i=0;i<8;i++)
		{					

			collection.get(i).remove(0);
			collection.get(i).add(newVal.get(index++));
		}

		writeAvgs(collection);
		collection= readAvgFile();
		refreshAvgValues();

	}

	private float[] inDecendeingOrder(float arr[])
	{

		Arrays.sort(arr);

		float [] a=new float[arr.length];

		for(int i=0; i<arr.length; i++)
			a[i]=arr[arr.length-(i+1)];
		return a;

	}


	public float getHotelPriceDiff(int in, int out)
	{
		float tt = 0f;
		float ss = 0f;
		for (int auction=in-1; auction<out-1; auction++)
			ss += getAvgValueOfHotel(auction);
		
		ss /= out-in+1; 
		//THIS IS THE REAL AVEGRAGE VALUE
		ss =(float)(ss-(ss*0.25));

		for (int auction=4+in-1; auction<4+out-1; auction++)
			tt += getAvgValueOfHotel(auction);
		tt /= out-in+1;
		tt =(float)(tt-(tt*0.25));
		
		log.fine("********* PACKAGE: SS = "+ss+" TT = "+tt+ " ---> "+(tt-ss));

		return tt-ss;
	}

	public float[] getBidPrices(int auction, Vector<Float> marginalValues, float askPrice,
			int minute, int HQW, boolean counterAuctionClosed) {

		float [] bidValues;

		if(minute==1)
			bidValues = prepareFirstMinuteBids(auction, marginalValues);
		else if(marginalValues.size()==0 & askPrice>15)
		{
			log.warning("THERE IS NO MARGINAL VALUE FOR THE AUCTION: "+auction);
			bidValues = new float[HQW];
			Arrays.fill(bidValues, askPrice+1);
			return bidValues;
		}
		else
			bidValues =  bidValue(auction, marginalValues, askPrice, minute, HQW, counterAuctionClosed);

		bidValues=prepareBasicBids(auction, bidValues, askPrice);

		if (bidValues.length< HQW) {
			float[] newBidValues = new float[HQW];

			for (int i=0; i<bidValues.length; i++)
				newBidValues[i] = bidValues[i];

			for (int i=bidValues.length; i<HQW; i++)
				newBidValues[i] = askPrice+1;

			bidValues = newBidValues;
		}

		//Last check: make sure that no bid is less than ask+1 
		
		for (int i = 0; i < bidValues.length; i++) {
			bidValues[i]=Math.max(bidValues[i], askPrice+1);
			
		}
				
		return bidValues;
	}
	
	public float[] prepareFirstMinuteBids(int auction, Vector<Float> marginalValues)
	{
		log.fine("IN PREPARE FIRST MINUTE METHOD");
		int hotelNumber = auction-8;

		if(hotelNumber<0 || hotelNumber>7)
		{
			log.fine("HOTEL VALUE IS INCORRECT:"+hotelNumber+"Excepted: >0 OR <8");
			return new float[0];
		}
		int divValue=(hotelNumber<4? 100:120);

		float valuesToMultiply[] = new float[]{1, 0.92f, 0.85f, 0.81f, 0.76f, 0.65f, 0.65f, 0.65f}; 

		float valuesToReturn[]=new float[marginalValues.size()];

		for(int i=0; i<marginalValues.size(); i++ )
		{
			float hotelAvg=getAvgValueOfHotel(hotelNumber);
			valuesToReturn[i]=Math.max(hotelAvg,(((hotelAvg+divValue)/2))*valuesToMultiply[i]);
			log.fine("THE AVERAGE COMPUTED VALUE IS "+(hotelAvg>divValue?hotelAvg:((hotelAvg+divValue)/2))*valuesToMultiply[i]);
			log.fine("THE HOTEL AVERAGE VALUE IS "+hotelAvg);
		}

		for (int i = 0; i < valuesToReturn.length; i++) {
			log.fine(""+valuesToReturn[i]);
		}
		return valuesToReturn; 



	}
	
	
	public  float[] bidValue(int auction, Vector<Float> marginalValues, float ask, int minute, int HQW, boolean counterAuctionClosed)
	{
		int alloc = marginalValues.size();
		int minutesToDivide=(9-minute);




		float[] bidValues=new float[alloc];

		for (int i = 0; i <bidValues.length; i++) {


			if(counterAuctionClosed)
			{
				log.fine("COUNTER AUCTION IS CLOSED AT MINUTE: "+minute);
				if(minute<5)
					bidValues[i]=(float)Math.max((ask+(marginalValues.get(i)-ask)/minutesToDivide), ((marginalValues.get(i))*0.8));
				else if(minute <7)
					bidValues[i]=(float)Math.max((ask+(marginalValues.get(i)-ask)/minutesToDivide), ((marginalValues.get(i))*0.9));
				else 
					bidValues[i]=(float)((marginalValues.get(i)));
			}
			
			else
				bidValues[i]=(float)(ask+(marginalValues.get(i)-ask)/minutesToDivide);
			
			if(ask>=marginalValues.get(i))
				bidValues[i]=marginalValues.get(i);
			
		}

		return inDecendeingOrder(bidValues);
	}
	

	protected float[] prepareBasicBids(int auction, float[] v, float askPrice)
	{
		log.fine("IN PREPARE BASIC BIDS METHOD: ASK RPICE = "+askPrice);
		for (int i = 0; i < v.length; i++) {
			log.fine(""+v[i]);
		}
		boolean cheapHotel = TACAgent.getAuctionType(auction) == TACAgent.TYPE_CHEAP_HOTEL;
		
		int c_values[]={12,10,5,2,1,1,1,1};  
		int g_values[]={15,12,10,5,2,1,1,1};

		int values[]=(cheapHotel?c_values:g_values);  	

		int valuesToAdd=0;
		for (int i = 0; i < values.length; i++) {
			if(askPrice<values[i] && (v.length+valuesToAdd<8))
				valuesToAdd++;
		}
		log.fine("VALUES TO ADD: "+valuesToAdd +" Values.length: "+values.length);

		if (valuesToAdd == 0)
			return v;
		
		float finalValues[]=new float[v.length+valuesToAdd];

		for(int i=0; i<v.length ; i++)
			finalValues[i]=v[i];


		for(int i= v.length;i<finalValues.length;i++)
			finalValues[i]=values[i-v.length];

		return inDecendeingOrder(finalValues);

	}


	private void writeAvgs(Vector<Vector> avg)
	{

		File f=new File(fileName);


		try {

			if(!f.exists())
				f.createNewFile();

			OutputStream file=new FileOutputStream(f);

			OutputStream buffer = new BufferedOutputStream(file);

			ObjectOutput output=new ObjectOutputStream(buffer);

			try{
				output.writeObject(avg);
			}
			finally{

				output.close();
			}


		} catch (FileNotFoundException e) {
			System.out.println(e);
		} catch (IOException e) {
			e.printStackTrace();
		}


	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub


		HotelBidding hb=new HotelBidding();
		Vector<Float> marginalValues = new Vector<Float>();


		marginalValues.add(400f);
		marginalValues.add(700f);
		marginalValues.add(400f);
		marginalValues.add(100f);
		//marginalValues.add(600f);
		//marginalValues.add(400f);
		//marginalValues.add(400f);
		//marginalValues.add(300f);
		float askPrice=4;

		int minute=8;

		float bidPrices[]=null;
	/*	try {
			bidPrices = hb.getBidPrices ( 15, marginalValues, askPrice, minute);
		} catch (Exception e) {

			e.printStackTrace();
		}*/
		System.out.println();
		for (int i = 0; i < bidPrices.length; i++) {
			System.out.println(bidPrices[i]);
		}


	}

}